﻿#include "chaiscript.h"

#include <opencv2/features2d.hpp>
#include <opencv2/xfeatures2d.hpp>

using namespace cv;
#ifdef __WITH_CHAISCRIPT__
ChaiScript chai;
#endif

void initFun_ChaiScript()
{
#ifdef __WITH_CHAISCRIPT__
    chai.add( chaiscript::fun(static_cast< cv::Ptr<cv::BRISK>(*)(int thresh, int octaves, float patternScale) >(&cv::BRISK::create)),"BRISK_create");

    chaiscript::ModulePtr m = chaiscript::ModulePtr(new chaiscript::Module());
    chaiscript::utility::add_class<ORB::ScoreType>(*m,
         "ORB_ScoreType",
         { { ORB::HARRIS_SCORE, "HARRIS_SCORE" },
           { ORB::FAST_SCORE, "FAST_SCORE" }
           }
    );
    chai.add(m);
    chai.add( chaiscript::fun(static_cast< cv::Ptr<cv::ORB>(*)(int nfeatures, float scaleFactor, int nlevels, int edgeThreshold,
                                                               int firstLevel, int WTA_K, ORB::ScoreType scoreType, int patchSize, int fastThreshold) >(&cv::ORB::create)),"ORB_create");

    chai.add( chaiscript::fun(static_cast< cv::Ptr<cv::MSER>(*)(int _delta, int _min_area, int _max_area,
                                                               double _max_variation, double _min_diversity,
                                                               int _max_evolution, double _area_threshold,
                                                               double _min_margin, int _edge_blur_size) >(&cv::MSER::create)),"MSER_create");

    chai.add( chaiscript::fun(static_cast< cv::Ptr<cv::FastFeatureDetector>(*)(int threshold, bool nonmaxSuppression,
                                                                FastFeatureDetector::DetectorType type) >(&cv::FastFeatureDetector::create)),"FAST_create");

    chai.add( chaiscript::fun(static_cast< cv::Ptr<cv::AgastFeatureDetector>(*)(int threshold,
                                                                                bool nonmaxSuppression,
                                                                                AgastFeatureDetector::DetectorType type ) >(&cv::AgastFeatureDetector::create)),"AGAST_create");

    chai.add( chaiscript::fun(static_cast< cv::Ptr<cv::GFTTDetector>(*)(int maxCorners, double qualityLevel, double minDistance,
                                                                        int blockSize, bool useHarrisDetector, double k) >(&cv::GFTTDetector::create)),"GFTT_create");

    //chai.add( chaiscript::fun(static_cast< cv::Ptr<cv::SimpleBlobDetector>(*)(SimpleBlobDetector::Params &parameters) >(&cv::SimpleBlobDetector::create)),"SimpleBlob_create");

    chai.add( chaiscript::fun(static_cast< cv::Ptr<cv::KAZE>(*)(bool extended, bool upright,
                                                                float threshold,
                                                                int nOctaves, int nOctaveLayers,
                                                                KAZE::DiffusivityType diffusivity) >(&cv::KAZE::create)),"KAZE_create");

    chai.add( chaiscript::fun(static_cast< cv::Ptr<cv::AKAZE>(*)(AKAZE::DescriptorType descriptor_type,
                                                                 int descriptor_size, int descriptor_channels,
                                                                 float threshold, int nOctaves,
                                                                 int nOctaveLayers, KAZE::DiffusivityType diffusivity) >(&cv::AKAZE::create)),"AKAZE_create");

    chai.add( chaiscript::fun(static_cast< cv::Ptr<cv::SIFT>(*)(int nfeatures, int nOctaveLayers,
                                                                             double contrastThreshold, double edgeThreshold,
                                                                             double sigma) >(&cv::SIFT::create)),"SIFT_create");

    chai.add( chaiscript::fun(static_cast< cv::Ptr<cv::xfeatures2d::SURF>(*)(double hessianThreshold,
                                                                             int nOctaves, int nOctaveLayers,
                                                                             bool extended, bool upright)>(&cv::xfeatures2d::SURF::create)),"SURF_create");

    chai.add( chaiscript::fun(static_cast< cv::Ptr<cv::xfeatures2d::FREAK>(*)(bool orientationNormalized,
                                                                              bool scaleNormalized,
                                                                              float patternScale,
                                                                              int nOctaves,
                                                                              const std::vector<int>& selectedPairs)>(&cv::xfeatures2d::FREAK::create)),"FREAK_create");

    chai.add( chaiscript::fun(static_cast< cv::Ptr<cv::xfeatures2d::StarDetector>(*)(int maxSize, int responseThreshold,
                                                                                      int lineThresholdProjected,
                                                                                      int lineThresholdBinarized,
                                                                                      int suppressNonmaxSize)>(&cv::xfeatures2d::StarDetector::create)),"StarDetector_create");

    chai.add( chaiscript::fun(static_cast< cv::Ptr<cv::xfeatures2d::BriefDescriptorExtractor>(*)(int bytes,
                                                                                                 bool use_orientation)>(&cv::xfeatures2d::BriefDescriptorExtractor::create)),"Brief_create");

    chai.add( chaiscript::fun(static_cast< cv::Ptr<cv::xfeatures2d::LUCID>(*)(const int lucid_kernel, const int blur_kernel)>(&cv::xfeatures2d::LUCID::create)),"LUCID_create");

    chai.add( chaiscript::fun(static_cast< cv::Ptr<cv::xfeatures2d::LATCH>(*)(int bytes, bool rotationInvariance,
                                                                              int half_ssd_size, double sigma)>(&cv::xfeatures2d::LATCH::create)),"LATCH_create");

    chai.add( chaiscript::fun(static_cast< cv::Ptr<cv::xfeatures2d::DAISY>(*)(float radius, int q_radius, int q_theta,
                                                                              int q_hist, xfeatures2d::DAISY::NormalizationType norm, InputArray H,
                                                                              bool interpolation, bool use_orientation)>(&cv::xfeatures2d::DAISY::create)),"DAISY_create");

    chai.add( chaiscript::fun(static_cast< cv::Ptr<cv::xfeatures2d::MSDDetector>(*)(int m_patch_radius, int m_search_area_radius,
                                                                                    int m_nms_radius, int m_nms_scale_radius, float m_th_saliency, int m_kNN,
                                                                                    float m_scale_factor, int m_n_scales,
                                                                                    bool m_compute_orientation)>(&cv::xfeatures2d::MSDDetector::create)),"MSDDetector_create");

    chai.add( chaiscript::fun(static_cast< cv::Ptr<cv::xfeatures2d::VGG>(*)(int desc, float isigma,
                                                                            bool img_normalize, bool use_scale_orientation,
                                                                            float scale_factor, bool dsc_normalize)>(&cv::xfeatures2d::VGG::create)),"VGG_create");

    chai.add( chaiscript::fun(static_cast< cv::Ptr<cv::xfeatures2d::BoostDesc>(*)(int desc,
                                                                                  bool use_scale_orientation,
                                                                                  float scale_factor)>(&cv::xfeatures2d::BoostDesc::create)),"BoostDesc_create");

//    }
////            else if (typeString == "PCT") {
////               Ptr<xfeatures2d::PCTSignatures> PctDetector  = cv::xfeatures2d::PCTSignatures::create();
////               PctDetector->detect(ProcImageMap["InImage"], mKeypoints);
////            }
////            else if (typeString == "PCTSQFD") {
////                Ptr<xfeatures2d::PCTSignaturesSQFD> PctDetector  = cv::xfeatures2d::PCTSignaturesSQFD::create();
////                PctDetector->detect(ProcImageMap["InImage"], mKeypoints);
////            }
    chai.add( chaiscript::fun(static_cast< cv::Ptr<cv::xfeatures2d::HarrisLaplaceFeatureDetector>(*)(int numOctaves,
                                                                                                     float corn_thresh,
                                                                                                     float DOG_thresh,
                                                                                                     int maxCorners,
                                                                                                     int num_layers)>(&cv::xfeatures2d::HarrisLaplaceFeatureDetector::create)),"HarrisLaplace_create");
////            else if (typeString == "Affine") {
////                Ptr<xfeatures2d::AffineFeature2D>
#endif
}

cv::Ptr<cv::FeatureDetector> GetDector_ChaiScript( const std::string lines)
{
    #ifdef __WITH_CHAISCRIPT__
    auto ret = chai.eval(lines);

    //这个只针对特征检测

    if(lines.find("BRISK") != std::string::npos)
    {
        return chai.boxed_cast<cv::Ptr<cv::BRISK>>(ret);
    }
    else if(lines.find("ORB") != std::string::npos)
    {
        return chai.boxed_cast<cv::Ptr<cv::ORB>>(ret);
    }
    else if(lines.find("MSER") != std::string::npos)
    {
        return chai.boxed_cast<cv::Ptr<cv::MSER>>(ret);
    }
    else if(lines.find("FAST") != std::string::npos)
    {
        return chai.boxed_cast<cv::Ptr<cv::FastFeatureDetector>>(ret);
    }
    else if(lines.find("AGAST") != std::string::npos)
    {
        return chai.boxed_cast<cv::Ptr<cv::AgastFeatureDetector>>(ret);
    }
    else if(lines.find("GFTT") != std::string::npos)
    {
        return chai.boxed_cast<cv::Ptr<cv::GFTTDetector>>(ret);
    }
    else if(lines.find("SimpleBlob") != std::string::npos)
    {
        return chai.boxed_cast<cv::Ptr<cv::SimpleBlobDetector>>(ret);
    }
    else if(lines.find("KAZE") != std::string::npos)
    {
        return chai.boxed_cast<cv::Ptr<cv::KAZE>>(ret);
    }
    else if(lines.find("AKAZE") != std::string::npos)
    {
        return chai.boxed_cast<cv::Ptr<cv::AKAZE>>(ret);
    }
    else if(lines.find("SIFT") != std::string::npos)
    {
        return chai.boxed_cast<cv::Ptr<cv::SIFT>>(ret);
    }
    else if(lines.find("SURF") != std::string::npos)
    {
        return chai.boxed_cast<cv::Ptr<cv::xfeatures2d::SURF>>(ret);
    }
    else if(lines.find("FREAK") != std::string::npos)
    {
        return chai.boxed_cast<cv::Ptr<cv::xfeatures2d::FREAK>>(ret);
    }
    else if(lines.find("StarDetector") != std::string::npos)
    {
        return chai.boxed_cast<cv::Ptr<cv::xfeatures2d::StarDetector>>(ret);
    }
    else if(lines.find("Brief") != std::string::npos)
    {
        return chai.boxed_cast<cv::Ptr<cv::xfeatures2d::BriefDescriptorExtractor>>(ret);
    }
    else if(lines.find("LUCID") != std::string::npos)
    {
        return chai.boxed_cast<cv::Ptr<cv::xfeatures2d::LUCID>>(ret);
    }
    else if(lines.find("LATCH") != std::string::npos)
    {
        return chai.boxed_cast<cv::Ptr<cv::xfeatures2d::LATCH>>(ret);
    }
    else if(lines.find("DAISY") != std::string::npos)
    {
        return chai.boxed_cast<cv::Ptr<cv::xfeatures2d::DAISY>>(ret);
    }
    else if(lines.find("MSDDetector") != std::string::npos)
    {
        return chai.boxed_cast<cv::Ptr<cv::xfeatures2d::MSDDetector>>(ret);
    }
    else if(lines.find("VGG") != std::string::npos)
    {
        return chai.boxed_cast<cv::Ptr<cv::xfeatures2d::VGG>>(ret);
    }
    else if(lines.find("BoostDesc") != std::string::npos)
    {
        return chai.boxed_cast<cv::Ptr<cv::xfeatures2d::BoostDesc>>(ret);
    }
//            else if (typeString == "PCT") {
//               Ptr<xfeatures2d::PCTSignatures> PctDetector  = cv::xfeatures2d::PCTSignatures::create();
//               PctDetector->detect(ProcImageMap["InImage"], mKeypoints);
//            }
//            else if (typeString == "PCTSQFD") {
//                Ptr<xfeatures2d::PCTSignaturesSQFD> PctDetector  = cv::xfeatures2d::PCTSignaturesSQFD::create();
//                PctDetector->detect(ProcImageMap["InImage"], mKeypoints);
//            }
    else if(lines.find("HarrisLaplace") != std::string::npos)
    {
        return chai.boxed_cast<cv::Ptr<cv::xfeatures2d::HarrisLaplaceFeatureDetector>>(ret);
    }
//            else if (typeString == "Affine") {
//                Ptr<xfeatures2d::AffineFeature2D> AffineDetector  = cv::xfeatures2d::AffineFeature2D::create(mKeypoints);
//                AffineDetector->detect(ProcImageMap["InImage"], mKeypoints);
//            }
    else {
        return nullptr;
    }
#else
    return cv::SIFT::create();
#endif
}
